package nl.harmidi.harmonictable;

import nl.harmidi.midi.MidiTranslator;
import nl.harmidi.midi.MyMidiEvent;
import nl.harmidi.midi.MyMidiEventsListenerInterface;
import nl.harmidi.swing.Hexagon;

public class Spot implements MyMidiEventsListenerInterface {
	protected int rowNumber;
	protected int columnNumber;
	protected int noteNumber;
	protected State state = State.OFF;
	protected int velocity;
	protected Hexagon linkedHexagon;

	public static enum State {
		ON, OFF, FADING
	}

	public Spot() {
	}

	public Spot(int rowNumber, int columnNumber, int noteNumber) {
		this.rowNumber = rowNumber;
		this.columnNumber = columnNumber;
		this.noteNumber = noteNumber;
	}

	public int getRowNumber() {
		return rowNumber;
	}

	public void setRowNumber(int rowNumber) {
		this.rowNumber = rowNumber;
	}

	public int getColumnNumber() {
		return columnNumber;
	}

	public void setColumnNumber(int columnNumber) {
		this.columnNumber = columnNumber;
	}

	public int getNoteNumber() {
		return noteNumber;
	}

	public void setNoteNumber(int noteNumber) {
		this.noteNumber = noteNumber;
	}

	public boolean send(MyMidiEvent event) {
		if (event.getNoteNumber() == noteNumber) {
			handleNewState(event);
			return true;
		}
		return false;
	}

	public void startVelocityFade(int stepSize) {
		state = State.FADING;
		// so a new note-on or note-off stops the fading
		while (velocity > 0 && state == State.FADING) {
			if (velocity - stepSize < 0) {
				velocity = 0;
				state = State.OFF;
				linkedHexagon.setState(Hexagon.State.OFF);
			} else {
				velocity -= stepSize;
			}
			linkedHexagon.setVelocity(velocity);
			try {
				Thread.sleep(30);
			} catch (Exception ignore) {
			}
		}

	}

	private void handleNewState(MyMidiEvent event) {
		velocity = event.getVelocity();

		switch (event.getType()) {
		case NOTE_ON:
			state = State.ON;
			break;
		case NOTE_OFF:
			state = State.OFF;
		}

		linkedHexagon.handleNewState(event);
	}

	public void reset() {
		state = State.OFF;
		linkedHexagon.reset();
	}

	public State getState() {
		return state;
	}

	public int getVelocity() {
		return velocity;
	}

	@Override
	public String toString() {
		return String.format("Spot (" + "[row=%s]" + "[column=%s]" + "[noteNr=%s]" + "[noteString=%s]" + "[state=%s]" + "[velocity=%s]" + ")", rowNumber,
				columnNumber, noteNumber, MidiTranslator.getKeyName(noteNumber), state == State.ON ? "ON" : "OFF", velocity);
	}

	public void setLinkedHexagon(Hexagon linkedHexagon) {
		this.linkedHexagon = linkedHexagon;
	}

}
